package grpc

import (
	"base_server/internal/models/customer_registration"
	"base_server/internal/models/cutpart"
	"base_server/internal/models/fashion"
	"base_server/internal/services"
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	common "jihe.common"
	"jihe.common/oss"
	"jihe.common/protos/base_server"
	"jihe.common/protos/base_server/proto"
	"jihe.common/protos/calculate_server"
	calculate_server_proto "jihe.common/protos/calculate_server/proto"
	"jihe.common/tool"
	"time"
)

func (s *Server) BaseGetFashionTypes(ctx context.Context, req *proto.BaseFashionTypes) (ret *proto.BaseFashionTypes, err error) {
	ret = new(proto.BaseFashionTypes)
	fashionTbl := fashion.NewModel(s.Pgsql.Get())
	tps, err := fashionTbl.GetTpByDistinct()
	if err != nil {
		return
	}
	ret.BaseFashionTypeList = append(ret.BaseFashionTypeList, &proto.BaseFashionType{Label: "推荐", Value: 9999})
	for _, v := range req.BaseFashionTypeList {
		for _, i := range tps {
			if v.Value == i {
				ret.BaseFashionTypeList = append(ret.BaseFashionTypeList, v)
				break
			}
		}
	}
	return
}

func (s *Server) BaseGetRecommendedFashions(ctx context.Context, req *proto.BaseNull) (ret *proto.BaseGetFashionListRes, err error) {
	ret = new(proto.BaseGetFashionListRes)
	fashionTbl := fashion.NewModel(s.Pgsql.Get())
	ret, err = fashionTbl.GetTpByRecommended()
	if err != nil {
		return
	}
	return
}

func (s *Server) UpdateBorderPointUrlById(ctx context.Context, req *proto.UpdateBorderPointUrlByIdReq) (ret *proto.BaseNull, err error) {
	ret = new(proto.BaseNull)
	fashionTbl := fashion.NewModel(s.Pgsql.Get())
	err = fashionTbl.UpdateBorderPointUrlById(req.Id, req.Url)
	if err != nil {
		return
	}
	return
}

func (s *Server) BaseGetFashionListByIds(ctx context.Context, req *proto.BaseGetFashionListByIdsReq) (ret *proto.BaseFashions, err error) {
	ret = new(proto.BaseFashions)
	fashionTbl := fashion.NewModel(s.Pgsql.Get())
	ret.BaseFashionList, err = fashionTbl.GetListByIds(req)
	if err != nil {
		return
	}
	return
}

func (s *Server) BaseSetRecommendedFashion(ctx context.Context, req *proto.BaseFashion) (ret *proto.BaseNull, err error) {
	ret = new(proto.BaseNull)
	fashionTbl := fashion.NewModel(s.Pgsql.Get())
	err = fashionTbl.UpdateRecommended(req.Id, req.Recommended)
	if err != nil {
		return
	}
	return
}

func (s *Server) BaseFashionOffline(ctx context.Context, req *proto.BaseFashion) (ret *proto.BaseNull, err error) {
	ret = new(proto.BaseNull)
	fashionTbl := fashion.NewModel(s.Pgsql.Get())
	err = fashionTbl.UpdateStatus(req.Id, req.Status)
	if err != nil {
		return
	}
	return
}

func (s *Server) BaseFashionDelete(ctx context.Context, req *proto.BaseFashion) (ret *proto.BaseNull, err error) {
	ret = new(proto.BaseNull)
	db := s.Pgsql.Get()
	tx, err := db.Begin()
	if err != nil {
		return
	}
	needTbl := customer_registration.NewModel(db)
	if needTbl.ExistFashionId(req.Id) {
		err = fmt.Errorf("errorno=1")
		return
	}
	fashionTbl := fashion.NewTx(tx)
	err = fashionTbl.Delete(req.Id)
	if err != nil {
		_ = tx.Rollback()
		return
	}
	cutpartTbl := cutpart.NewTx(tx)
	err = cutpartTbl.DeleteByFashionId(req.Id)
	if err != nil {
		_ = tx.Rollback()
		return
	}
	err = tx.Commit()
	if err != nil {
		_ = tx.Rollback()
		return
	}
	return
}

func (s *Server) HandleUpdateObjUrl(ctx context.Context, req *proto.HandleUpdateObjUrlReq) (ret *proto.BaseNull, err error) {
	ret = new(proto.BaseNull)
	redisClient := s.Redis.Get()
	redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "uploading", time.Hour*2)
	go func() {
		tx, err := s.Pgsql.Get().Begin()
		if err != nil {
			redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "error", time.Hour*2)
			common.Loger.Error("%v", err)
			return
		}

		cuts, err := tool.SplitObj(req.ObjUrl)
		if err != nil {
			_ = tx.Rollback()
			common.Loger.Error("%v", err)
			redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "error", time.Hour*2)
			return
		}
		cutpartTbl := cutpart.NewTx(tx)
		err = cutpartTbl.DeleteByFashionId(req.FashionId)
		if err != nil {
			_ = tx.Rollback()
			common.Loger.Error("%v", err)
			redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "error", time.Hour*2)
			return
		}
		err = cutpartTbl.BatchCreate(&proto.BaseCutparts{FashionId: req.FashionId, BaseCutpartList: cuts})
		if err != nil {
			_ = tx.Rollback()
			common.Loger.Error("%v", err)
			redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "error", time.Hour*2)
			return
		}
		vtInfos := make([]base_server.VtInfo, 0)
		for _, v := range cuts {
			item := base_server.VtInfo{}
			res, e := calculate_server.GetBorderNode(context.Background(), &calculate_server_proto.GetBorderNodeReq{ObjUrl: v.ObjUrl})
			if e != nil {
				err = e
				_ = tx.Rollback()
				common.Loger.Error("%v", err)
				redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "error", time.Hour*2)
				return
			}
			err = json.Unmarshal([]byte(res.Stdout), &item)
			if err != nil {
				_ = tx.Rollback()
				common.Loger.Error("%v", err)
				redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "error", time.Hour*2)
				return
			}

			afterUvRet, e := calculate_server.CalibrationUv(context.Background(), &calculate_server_proto.CalibrationUvReq{Url: v.ObjUrl})
			if e != nil {
				err = e
				_ = tx.Rollback()
				common.Loger.Error("%v", err)
				redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "error", time.Hour*2)
				return
			}
			afterUv := make([][]float64, 0)
			err = json.Unmarshal([]byte(afterUvRet.Stdout), &afterUv)
			if err != nil {
				_ = tx.Rollback()
				common.Loger.Error("%v %s", err, afterUvRet.Stdout)
				redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "error", time.Hour*2)
				return
			}
			path := fmt.Sprintf("calibration_uv/%s/%s.obj", req.FashionId, v.Code)
			_, err = tool.MakeAfterObjByPath(v.ObjUrl, afterUv, path)
			if err != nil {
				_ = tx.Rollback()
				common.Loger.Error("%v", err)
				redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "error", time.Hour*2)
				return
			}
			item.Code = v.Code
			vtInfos = append(vtInfos, item)
		}
		bucket, err := oss.GetClient().Bucket("jihe-file")
		if err != nil {
			_ = tx.Rollback()
			common.Loger.Error("%v", err)
			redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "error", time.Hour*2)
			return
		}
		jsonByte, err := json.Marshal(vtInfos)
		if err != nil {
			_ = tx.Rollback()
			common.Loger.Error("%v", err)
			redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "error", time.Hour*2)
			return
		}
		fileName := fmt.Sprintf("%s/%d.json", time.Now().Format("2006-01-02"), tool.GetSnowflakeId())
		err = bucket.PutObject(fileName, bytes.NewReader(jsonByte))
		if err != nil {
			_ = tx.Rollback()
			common.Loger.Error("%v", err)
			redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "error", time.Hour*2)
			return
		}
		cutpartPointUrl := "https://files.dizanz.com/" + fileName
		//检测是否已有dxf，如果有更新dxf_info
		fashionDetail, _ := fashion.NewModel(s.Pgsql.Get()).GetDetail(req.FashionId)
		if fashionDetail != nil {
			if fashionDetail.DxfUrl != "" {
				cutpartPointUrl, err = services.UpdateDxfInfo(req.FashionId, fashionDetail.DxfUrl, req.ObjUrl, cutpartPointUrl, cuts)
				if err != nil {
					common.Loger.Error("%v", err)
					redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "error", time.Hour*2)
					_ = tx.Rollback()
					return
				}
			}
		}
		err = fashion.NewModel(s.Pgsql.Get()).UpdateCutpartBorderPointById(req.FashionId, cutpartPointUrl, req.ObjUrl)
		if err != nil {
			_ = tx.Rollback()
			common.Loger.Error("%v", err)
			redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "error", time.Hour*2)
			return
		}
		err = tx.Commit()
		if err != nil {
			common.Loger.Error("%v", err)
			_ = tx.Rollback()
			redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "error", time.Hour*2)
			return
		}
		redisClient.Set(s.Redis.GetUploadFashionObjKey(req.FashionId), "success", time.Hour*2)
	}()
	return
}
